/**
 * 
 */
package datamodel.tree.sequential;

import java.util.ArrayList;
import java.util.List;

import datamodel.tree.Tree;
import datamodel.tree.TreeNode;

/**
 * An implementation of the tree interface.<br>
 * uses a sequential construction
 * 
 * @author Jakob Karolus, Kevin Munk
 * @version 1.0
 * 
 */
public class SequentialTree extends Tree {
	
	private List<TreeNode> tree = new ArrayList<TreeNode>();
	private int currentNodePos = 0;

	@Override
	public boolean moveToLeftNode() {
		if(hasLeftNode()) {
			currentNodePos = 2*currentNodePos+1;
			return true;
		} else return false;
	}

	@Override
	public boolean moveToRightNode() {
		if(hasRightNode()) {
			currentNodePos = 2*currentNodePos+2;
			return true;
		} else return false;
	}

	@Override
	public boolean moveToParentNode() {
		if(hasParentNode()){
			if(currentNodePos % 2 == 0) {
				currentNodePos = (currentNodePos - 2) / 2;
			}else{
				currentNodePos = (currentNodePos - 1) / 2;
			}
			return true;
		}
		return false;
	}

	@Override
	public boolean hasLeftNode() {
		return currentNodePos*2+1 < tree.size() && tree.get(currentNodePos*2+1) != null;
	}

	@Override
	public boolean hasRightNode() {
		return currentNodePos*2+2 < tree.size() && tree.get(currentNodePos*2+2) != null;
	}

	@Override
	public boolean hasParentNode() {
		if(currentNodePos != 0){
			if(currentNodePos % 2 == 0) {
				return tree.get((currentNodePos-2)/2) != null;
			}else{
				return tree.get((currentNodePos-1)/2) != null;
			}
		}
		return false;
	}

	@Override
	public boolean setLeftNode(TreeNode node) {
		if(tree.get(currentNodePos) != null) {
			for(int i = tree.size(); i <= 2*currentNodePos+1; i++) {
				tree.add(null);
			}
			tree.set(2*currentNodePos+1, node);
			return true;
		} else return false;
	}

	@Override
	public boolean setRightNode(TreeNode node) {
		if(tree.get(currentNodePos) != null) {
			for(int i = tree.size(); i <= 2*currentNodePos+2; i++) {
				tree.add(null);
			}
			tree.set(2*currentNodePos+2, node);
			return true;
		} else return false;
	}

	@Override
	public void setCurrentNode(TreeNode node) {
		if(tree.isEmpty()) {
			tree.add(node);
		} else {
			for(int i = tree.size(); i <= currentNodePos; i++) {
				tree.add(null);
			}
			tree.set(currentNodePos, node);
		}
		
	}

	@Override
	public TreeNode getCurrentNode() {
		if(tree.isEmpty()) {
			return null;
		} else return tree.get(currentNodePos);
	}

	@Override
	public boolean moveToRoot() {
		if(tree.size() > 0 && tree.get(0) != null) {
			currentNodePos = 0;
			return true;
		}
		else return false;
	}

	@Override
	public void clearTree() {
		tree.clear();
		currentNodePos = 0;
	}
}
